﻿/*
 * Created by: Ahmedzhanov Nail,400,438534,,J2EE
 * Created: Tuesday, March 27, 2007
 */

using System;
using System.Collections.Generic;
using Edge.Business.Security;
using Edge.Common.Services;
using Edge.Business.Entities;
using Edge.Business.Stat;
using Edge.DAL.Common.SessionManagment;
using NHibernate;
using NHibernate.Type;

namespace Edge.DAL.Managers
{
    public class SessionInterceptor : BaseManager, IInterceptorProvider
    {
        private Interceptor interceptor;


        public SessionInterceptor()
        {
            interceptor = new Interceptor(this);

        }

        public bool OnModified(object entity, object[] state, string[] propertyNames, bool newEntity)
        {
            object stat = entity as EntityWithStat<int>;
            if (stat != null)
            {
                FlushMode old = Session.FlushMode;
                Session.FlushMode = FlushMode.Commit;
              
                    EntityState entityState = new EntityState(state, propertyNames);
                BaseEntity<int> author = null;
                try
                {
                    author = Locator.GetService<IPersonManager<UserEntity<int>>>().GetCurrentAuthor();
                }
                catch(Exception ex)
                {
                }
                if (IsNewObject(entity) && newEntity)
                    {
                        entityState["CreateDate"] = DateTime.Now;
                        entityState["CreatedBy"] = author;
                    }

                    entityState["ModifyDate"] = DateTime.Now;
                    entityState["ModifiedBy"] = author;
                    Session.FlushMode = old;
                    return true;
                    

            }
            return false;
        }

        public bool OnFlushDirty(object entity, object id, object[] currentState, object[] previousState,
                                 string[] propertyNames, IType[] types)
        {
            if (previousState != null && previousState != currentState)
            {
                List<int> items = new List<int>();
                for (int j = 0; j < currentState.Length; j++)
                {
                    if (currentState[j] != null && previousState[j] != null && currentState[j].ToString() != previousState[j].ToString())
                    {
                        items.Add(j);
                    }
                }
                if (items.Count > 0)
                {
//                    TODO
                    //foreach (int item in items)
//                    {
//                        EntityLog el = new EntityLog(entity.GetType().Name, (int) id, propertyNames[item],
//                                                     previousState[item].ToString(), currentState[item].ToString());
//                        Locator.GetService<IEntityLogManager>().Save(el);
//                    }
                    return OnModified(entity, currentState, propertyNames, false);
                }
            }
            return false;
        }

        public bool OnSave(object entity, object id, object[] state, string[] propertyNames, IType[] types)
        {
            return OnModified(entity, state, propertyNames, true);
        }

        class EntityState
        {
            private object[] state;
            private string[] propertyNames;


            public EntityState(object[] state, string[] propertyNames)
            {
                this.state = state;
                this.propertyNames = propertyNames;
            }

            public object this[string propertyName]
            {
                get
                {
                    return state[FindIdx(propertyName)];
                }
                set
                {
                    state[FindIdx(propertyName)] = value;
                }
            }

            protected int FindIdx(string propertyName)
            {
                int idx = Array.IndexOf(propertyNames, propertyName);
                if (idx == -1)
                    throw new ArgumentException("property does not exists " + propertyName);
                return idx;
            }
        }

        #region IInterceptorProvider Members

        public IInterceptor GetInterceptor(ISessionFactory factory)
        {
            return interceptor;
        }

        #endregion
    }

    class Interceptor : EmptyInterceptor
    {
        private readonly SessionInterceptor sessionInterceptor;


        public Interceptor(SessionInterceptor sessionInterceptor)
        {
            if (sessionInterceptor == null)
                throw new ArgumentException("sessionInterceptor");
            this.sessionInterceptor = sessionInterceptor;
        }

        public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, IType[] types)
        {
            return sessionInterceptor.OnSave(entity, id, state, propertyNames, types);
        }


        public override bool OnFlushDirty(object entity, object id, object[] currentState, object[] previousState,
                                          string[] propertyNames, IType[] types)
        {
            return sessionInterceptor.OnFlushDirty(entity, id, currentState, previousState, propertyNames, types);
        }

    }
}